#pragma once
#include <cerrno>
#include <cstddef>
#include <iostream>
#include <sys/socket.h>
#include "Common.hpp"
#include "Connection.hpp"
#include "Log.hpp"
#include "InetAddr.hpp"
using namespace LogModule;
#define SIZE 1024
class Channel : public Connection { // 已经accept之后的文件描述符
public:
    Channel(int sockfd, const InetAddr& client) : _sockfd(sockfd), _client(client) {
        SetNonBlock(_sockfd);
    }
    void Recver() override { // 这里是ET模式所以是循环读
        char buffer[1024];
        while (true) {
            buffer[0] = 0;
            int n = recv(_sockfd, buffer, sizeof(buffer) - 1, 0);
            if(n > 0) {
                buffer[n] = '\0';
                _inbuffer += buffer;
            }else if(n == 0) {
                Excepter();
                return;
            }else {
                if(errno == EAGAIN || errno == EWOULDBLOCK) {
                    break;
                }else if(errno == EINTR) {
                    continue;
                }else {
                    Excepter();
                    return;
                }
            }
        }
        LOG(LogLevel::DEBUG) << "channel : inbuffer: " << _inbuffer;
        if(!_inbuffer.empty()) {
            _outbuffer += _handler(_inbuffer);
        }
        if(!_outbuffer.empty()) {
            Sender();
        }
    }
    void Sender()override {
        while (true) {
            size_t n = send(_sockfd, _outbuffer.c_str(), _outbuffer.size(), 0);
            if(n > 0) {
                _outbuffer.erase(0, n);
                if(_outbuffer.empty()) {
                    break;
                }
            }else if(n == 0) {
                break;
            }else {
                if(errno == EAGAIN || errno == EWOULDBLOCK) {
                    break;
                }
                if(errno == EINTR) continue;
                else {
                    Excepter();
                    break;
                }
            }
        }
        if(!_outbuffer.empty()) {
            GetOwner()->EnableReadWrite(_sockfd, true, true);
        }else {
            GetOwner()->EnableReadWrite(_sockfd, true, false);
        }
    }
    void Excepter() override{
        GetOwner()->DelConnection(_sockfd);
    }   
    int GetSockFd() override {
        return _sockfd;
    }
    std::string& Inbuffer() {
        return _inbuffer;
    }
    void AppendOutBuffer(const std::string& out) {
        _outbuffer += out;
    }
    ~Channel() {}
private:
    int _sockfd;
    std::string _inbuffer;
    std::string _outbuffer;
    InetAddr _client;
};